package com.lb.annotationmapper;

import com.lb.utils.MyBatisReflectUtil;
import org.apache.ibatis.jdbc.SQL;

import javax.persistence.Column;
import java.lang.reflect.Field;
import java.util.Map;

public class ProviderTemplate<T> extends MyBatisReflectUtil {
    public String insert(Map<String, Object> map) {
        final T obj = (T) map.get("pojo");
        caculationColumnList(obj);
        String sql = new SQL() {{
            INSERT_INTO(tablename(obj));
            VALUES(returnInsertTableColumnsName(obj), returnInsertAttrColumnsName(obj));
        }}.toString();
        return sql;
    }

    public String insertMap(Map<String, Object> map) {
        final String tableName = map.get("tableName").toString();
        Map<String,Object> obj= (Map) map.get("pojo");
        Map newObj= getSortMapByKey(obj,true);
        String sql = new SQL() {{
            INSERT_INTO(tableName);
            VALUES(returnInsertTableColumnsNameByMap(newObj), returnInsertAttrColumnsNameMap(newObj));
        }}.toString();
        return sql;
    }
    public String updateMap(Map<String, Object> map) {
        final String tableName = map.get("tableName").toString();
        Map<String,Object> obj= (Map) map.get("pojo");
        Map<String,Object> newObj= getSortMapByKey(obj,true);
        String idname="id";
        String sql = new SQL() {{
            UPDATE(tableName);
            SET(returnUpdateSetMap(newObj));
            WHERE(idname + "=#{pojo." + idname + "}");
        }}.toString();
        return sql;
    }

    public String update(Map<String, Object> map) {
        String sql = "";
        final T obj = (T) map.get("pojo");
         Field idname = idNew(obj);
         String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
        caculationColumnList(obj);
        sql = new SQL() {{
            UPDATE(tablename(obj));
            SET(returnUpdateSet(obj));
            WHERE(dataIdname + "=#{pojo." + idname.getName() + "}");
        }}.toString();
        return sql;

    }

    public String updateNew(Map<String, Object> map) {
        String sql = "";
        final T obj = (T) map.get("pojo");
         Field idname = idNew(obj);
         String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
        caculationColumnList(obj);
        sql = new SQL() {{
            UPDATE(tablename(obj));
            SET(returnUpdateSetNew(obj));
            WHERE(dataIdname + "=#{pojo." + idname.getName() + "}");
        }}.toString();
        return sql;

    }

    public String updateNewByWhereMap( Map<String, Object> map) {
        String sql = "";
        final T obj = (T) map.get("pojo");
        final Map<String, Object> whereMap = (Map) map.get("whereMap");
        final Field idname = idNew(obj);
        final String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
        caculationColumnList(obj);
        Map m = getAllAttrField(obj);
        Map<String,Field> fieldsMap= (Map<String, Field>) m.get("fieldsMap");
        sql = new SQL() {{
            String whereSql="";
            if(whereMap != null &&whereMap.containsKey(idname.getName())){
                whereSql += dataIdname + "=#{pojo." + idname.getName() + "}";
            }
            if (whereMap != null && whereMap.size() > 0) {
                for (Map.Entry<String, Object> entry : whereMap.entrySet()) {
                    //获取字段名及列名名称
                    String key = entry.getKey();
                    //entry.getValue();
                    Field f=fieldsMap.get(key);
                    final String dataFieldName=f.isAnnotationPresent(Column.class)?f.getAnnotation(Column.class).name():f.getName();
                    whereSql += "  and " + dataFieldName + "=#{whereMap." + key + "}  ";
                }
            }
            UPDATE(tablename(obj));
            SET(returnUpdateSetNew(obj));
            WHERE(whereSql);
        }}.toString();
        return sql;
    }
    public String updateNewByWhere(Map<String, Object> map) {
        String sql = "";
        final T obj = (T) map.get("pojo");
        final Map<String, Object> where = (Map) map.get("where");
        final Field idname = idNew(obj);
        final String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
        caculationColumnList(obj);
        Map mp = getAllAttrField(obj);
        Map<String,Field> fieldsMap= (Map<String, Field>) mp.get("fieldsMap");
        sql = new SQL() {{
            String whereSql = dataIdname + "=#{pojo." + idname.getName() + "}";
            if (where != null && where.size() > 0) {
                for (Map.Entry<String, Object> entry : where.entrySet()) {
                    //获取字段名及列名名称
                    String key = entry.getKey();
                    //entry.getValue();
                    Field f=fieldsMap.get(key);
                    final String dataFieldName=f.isAnnotationPresent(Column.class)?f.getAnnotation(Column.class).name():f.getName();
                    whereSql += "  and " + dataFieldName + "=#{where." + key + "}  ";
                }
            }
            UPDATE(tablename(obj));
            SET(returnUpdateSetNew(obj));
            WHERE(whereSql);
        }}.toString();
        return sql;

    }

    public String updateNewByWhereSql(Object obj, String otherWhereSql) {
        String sql = "";
        final Field idname = idNew(obj);
        final String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
        caculationColumnList(obj);
        sql = new SQL() {{
            String whereSql = dataIdname + "=#{pojo." + idname.getName() + "}";
            if (null != otherWhereSql && !"".equals(otherWhereSql)) {
                whereSql += otherWhereSql;
            }
            UPDATE(tablename(obj));
            SET(returnUpdateSetNew(obj));
            WHERE(whereSql);
        }}.toString();
        return sql;

    }
    public String delete(Map<String, Object> map) {
        final T obj = (T) map.get("pojo");
        String sql = "";
         Field idname = idNew(obj);
         String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
        caculationColumnList(obj);
        sql = new SQL() {{
            DELETE_FROM(tablename(obj));
            WHERE(dataIdname + "=#{pojo." + idname.getName() + "}");
        }}.toString();
        return sql;
    }

    public String deleteById(final Class clazz, final String id) {
        String sql = "";
        final Object obj;
        try {
            obj = clazz.newInstance();
             Field idname = idNew(obj);
             String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
            sql = new SQL() {{
                DELETE_FROM(tablename(obj));
                WHERE(dataIdname + "='" + id + "'");
            }}.toString();
        } catch (InstantiationException | IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return sql;
    }

    public String select(Map<String, Object> map) {
        final T obj = (T) map.get("pojo");
        String sql = "";
         Field idname = idNew(obj);
         String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
        caculationColumnList(obj);
        sql = new SQL() {{
            SELECT(returnInsertTableColumnsName(obj));
            FROM(tablename(obj));
            WHERE(dataIdname + "=#{pojo." + idname.getName() + "}");
        }}.toString();
        return sql;
    }

    public String selectAll(Class clazz) {
        String sql = "";
        try {
            final Object obj = clazz.newInstance();
            caculationColumnList(obj);
            sql = new SQL() {{
                SELECT(returnColumnsDefine(obj));
                FROM(tablename(obj));
            }}.toString();
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return sql;
    }

    public String countBySql(String countsql) {
        return countsql;
    }

    public String count(final Class clazz) {
        String sql = "";
        try {
            final Object obj = clazz.newInstance();
            sql = new SQL() {{
                SELECT("count(*)");
                FROM(tablename(obj));
            }}.toString();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return sql;
    }

    public String selectById(final Class clazz, final String id) {
        String sql = "";
        try {
            final Object obj = clazz.newInstance();
             Field idname = idNew(obj);
             String dataIdname =idname.isAnnotationPresent(Column.class)?idname.getAnnotation(Column.class).name():idname.getName();
            caculationColumnList(obj);
            sql = new SQL() {{
                SELECT(returnColumnsDefine(obj));
                FROM(tablename(obj));
                WHERE(dataIdname + "='" + id + "'");
            }}.toString();
        } catch (Exception e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return sql;
    }

}